package com.global.security.enviroment;

import com.bean.ClassUtil;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Sercurity environment post processor
 *
 * @description: 配置数据源加密
 * @author: cyj
 * @date 2022 -05-26 17:21:41
 *
 *
 */
@Component
public class SercuityEnvironmentListener implements SmartApplicationListener, Ordered {

    @Override
    public int getOrder() {
        return ConfigFileApplicationListener.DEFAULT_ORDER + 1;
    }

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return ApplicationPreparedEvent.class.isAssignableFrom(eventType);
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return true;
    }


    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        ApplicationPreparedEvent applicationPreparedEvent = (ApplicationPreparedEvent) event;

        ConfigurableEnvironment environment = applicationPreparedEvent.getApplicationContext().getEnvironment();

        MutablePropertySources propertySources = environment.getPropertySources();
        Iterator<PropertySource<?>> iterator = propertySources.iterator();

        EnviromentSecurity enviromentSecurity = getEnviromentSecurity();

        Map<String, Object> sercurityProperty = new HashMap<>();

        if (null != enviromentSecurity) {
            while (iterator.hasNext()) {
                PropertySource<?> propertySource = iterator.next();
                Object source = propertySource.getSource();
                if (source instanceof Map) {
                    Map<String, Object> sourceMap = (Map<String, Object>) source;
                    for (String key:
                            sourceMap.keySet()) {
                        String value = String.valueOf(sourceMap.get(key));
                        if (value.startsWith(EnviromentSecurity.ENCRYPT_PRFIX)) {
                            String encrypt = enviromentSecurity.encrypt(value);
                            sercurityProperty.put(key, encrypt);
                        } else if (value.startsWith(EnviromentSecurity.DECRYPT_PRFIX)) {
                            String decrypt = enviromentSecurity.decrypt(value);
                            sercurityProperty.put(key, decrypt);
                        }
                    }
                }
            }
        }

        /**
         * 将解密的数据放入环境变量，并处于第一优先级上
         * (这里一定要注意，覆盖其他配置)
         */
        if (!sercurityProperty.isEmpty()) {
            environment.getPropertySources().addFirst(new MapPropertySource("sercurityProperty", sercurityProperty));
        }
    }

    private EnviromentSecurity getEnviromentSecurity() {
        // 选择
        Set<EnviromentSecurity> subTypesOf = ClassUtil.getSubTypesOf(EnviromentSecurity.class);

        EnviromentSecurity enviromentSecurity = null;
        for (EnviromentSecurity enviromentSecurityTemp:
             subTypesOf) {
            if (null == enviromentSecurity || (enviromentSecurityTemp.getOrder() > enviromentSecurity.getOrder())) {
                enviromentSecurity = enviromentSecurityTemp;
            }
        }
        return enviromentSecurity;
    }
}
